import re
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from datetime import datetime

# 设置matplotlib以支持中文显示
plt.rcParams['font.sans-serif'] = ['SimHei']  # 或者 'Microsoft YaHei'
plt.rcParams['axes.unicode_minus'] = False


def analyze_backtest_results(file_path):
    """
    读取并分析回测结果txt文件，计算指标并绘图。
    """
    try:
        with open(file_path, 'r', encoding='utf-8') as f:
            content = f.read()
    except FileNotFoundError:
        print(f"错误：找不到文件 '{file_path}'。请确保文件名正确且文件在同一目录下。")
        return

    # 使用正则表达式分割每个交易记录块
    blocks = re.split(r'\[main\] INFO com\.ygy\.portfolio\.Portfolio -', content)

    trades = []
    equity_curve = []
    initial_capital = 10000.0  # 初始资金

    # 添加初始资金点
    first_trade_time_str = re.search(r"交易时间: ([\dT\-:\+]+)", blocks[1])
    if first_trade_time_str:
        start_time = datetime.fromisoformat(first_trade_time_str.group(1))
        equity_curve.append({'timestamp': start_time, 'balance': initial_capital})

    # 解析每个交易块
    for block in blocks:
        if "平仓" not in block and "止损" not in block:
            continue

        pnl_match = re.search(r"本笔盈亏: (-?[\d\.]+)", block)
        time_match = re.search(r"交易时间: ([\dT\-:\+]+)", block)
        balance_match = re.search(r"账户余额: ([\d\.]+)", block)
        trade_type_match = re.search(r"========= \[(.+)\] =========", block)

        if not all([pnl_match, time_match, balance_match, trade_type_match]):
            continue

        pnl = float(pnl_match.group(1))
        timestamp = datetime.fromisoformat(time_match.group(1))
        balance = float(balance_match.group(1))
        trade_type = trade_type_match.group(1)

        equity_curve.append({'timestamp': timestamp, 'balance': balance})

        # 判断是多头交易还是空头交易的平仓
        # 平多头 = 空头盈利；平空头 = 多头盈利
        if "多头" in trade_type:
            direction = "Short"
        elif "空头" in trade_type:
            direction = "Long"
        else:
            continue

        trades.append({
            'pnl': pnl,
            'direction': direction,
            'timestamp': timestamp
        })

    # --- 1. 数据准备 ---
    if not trades:
        print("未在文件中找到任何平仓或止损记录。")
        return

    df_trades = pd.DataFrame(trades)
    df_equity = pd.DataFrame(equity_curve).drop_duplicates(subset='timestamp').set_index('timestamp')

    # --- 2. 计算各项指标 ---
    # 总体指标
    final_equity = df_equity['balance'].iloc[-1]
    total_net_profit = final_equity - initial_capital
    total_return_pct = (total_net_profit / initial_capital) * 100

    total_trades = len(df_trades)
    winning_trades = df_trades[df_trades['pnl'] > 0]
    losing_trades = df_trades[df_trades['pnl'] <= 0]

    win_rate_pct = (len(winning_trades) / total_trades) * 100 if total_trades > 0 else 0

    gross_profit = winning_trades['pnl'].sum()
    gross_loss = abs(losing_trades['pnl'].sum())
    profit_factor = gross_profit / gross_loss if gross_loss > 0 else float('inf')

    # 最大回撤计算
    peak = df_equity['balance'].cummax()
    drawdown = (peak - df_equity['balance']) / peak
    max_drawdown_pct = drawdown.max() * 100

    # 夏普比率计算 (按单笔交易回报率)
    trade_returns = df_trades['pnl'] / df_equity['balance'].shift(1).loc[df_trades['timestamp']].values
    sharpe_ratio = (trade_returns.mean() / trade_returns.std()) * np.sqrt(
        252) if trade_returns.std() != 0 else 0  # 假设一年252个交易日进行年化

    # 多空分类指标
    long_trades = df_trades[df_trades['direction'] == 'Long']
    short_trades = df_trades[df_trades['direction'] == 'Short']

    long_pnl = long_trades['pnl'].sum()
    short_pnl = short_trades['pnl'].sum()

    long_win_rate = (len(long_trades[long_trades['pnl'] > 0]) / len(long_trades)) * 100 if len(long_trades) > 0 else 0
    short_win_rate = (len(short_trades[short_trades['pnl'] > 0]) / len(short_trades)) * 100 if len(
        short_trades) > 0 else 0

    # --- 3. 打印分析报告 ---
    print("=" * 50)
    print("               策略回测绩效报告")
    print("=" * 50)
    print(f"回测周期: {df_equity.index.min().date()} to {df_equity.index.max().date()}")
    print("\n--- 核心指标 ---")
    print(f"初始资金:           {initial_capital:,.2f}")
    print(f"最终权益:           {final_equity:,.2f}")
    print(f"总净利润:           {total_net_profit:,.2f}")
    print(f"累计收益率:         {total_return_pct:.2f}%")
    print(f"最大回撤:           {max_drawdown_pct:.2f}%")
    print(f"夏普比率 (年化):    {sharpe_ratio:.2f}")

    print("\n--- 交易统计 ---")
    print(f"总交易次数:         {total_trades}")
    print(f"胜率:               {win_rate_pct:.2f}%")
    print(f"盈利因子:           {profit_factor:.2f}")
    print(f"盈利交易数:         {len(winning_trades)}")
    print(f"亏损交易数:         {len(losing_trades)}")

    print("\n--- 多空表现分析 ---")
    print(f"做多总盈亏:         {long_pnl:,.2f}")
    print(f"做多胜率:           {long_win_rate:.2f}%")
    print(f"做多交易次数:       {len(long_trades)}")
    print("-" * 20)
    print(f"做空总盈亏:         {short_pnl:,.2f}")
    print(f"做空胜率:           {short_win_rate:.2f}%")
    print(f"做空交易次数:       {len(short_trades)}")
    print("=" * 50)

    # --- 4. 绘制资金权益曲线 ---
    plt.figure(figsize=(14, 7))
    plt.plot(df_equity.index, df_equity['balance'], label='资金权益')
    plt.title('资金权益曲线')
    plt.xlabel('日期')
    plt.ylabel('账户权益')
    plt.grid(True)
    plt.legend()
    plt.tight_layout()
    plt.show()


# --- 主程序入口 ---
if __name__ == '__main__':
    # 将'回测结果.txt'替换为你的实际文件名
    log_file_path = 'C:\\Users\\Sunny\\Desktop\\回测结果.txt'
    analyze_backtest_results(log_file_path)